/**
 * @name alipay
 * 支付宝支付系统
 * 提现SDK：https://docs.open.alipay.com/309/106236/
 */


"use strict"
const fs = require('fs');
const sign_type = "RSA2";
const order_from = "alipay";
const crypto = require('crypto');
//const alipay_sdk  = {};

exports.format = {
    "id":order_from,
    "name":"支付宝支付",
    "fields" : {
        appid :{'type':'string','val':''},
        PublicKey :{'type':'string','val':''},
        PrivateKey :{'type':'string','val':''},
    }
};


/**
 * @name login
 */

exports.login = function(){
    return this.error("alipay login not exist")
}


/**
 * @name createOrder
 * 创建订单
 */
exports.createOrder = function createOrder(config,notify){
    let id = config['orderid'];
    let api = "alipay.trade.app.pay";
    let data = {};
    data["body"] = config['describe']||'';
    data["subject"] = config['name'];
    data["out_trade_no"] = id;
    data["timeout_express"] = "90m";
    data["total_amount"] = String(config['rmb']);
    data["product_code"] = "QUICK_MSECURITY_PAY";
    data["goods_type"] = "0";
    data["passback_params"] = config['attach'];


    return alipay_sign.call(this,api,data,notify,0).then(body=>{
        return {"orderid":id,"attach":data["attach"],"rmb":config['rmb'], "body" : body };
    })
}




/**
 * @name orderNotify
 * 支付回调
 */

exports.orderNotify = function(){
    let attach = this.get('passback_params','string');
    let orderid = this.get('trade_no','string');
    if(!attach || !orderid){
        return this.error("args empty");
    }

    let sign = this.get('sign','string');
    let params = this.req.body;
    delete params["sign"];
    delete params["sign_type"];
    return RSA2.verify.call(this,params,sign).then(ret=>{
        if( !ret ){
            return Promise.error("sign error")
        }
        else{
            return {"attach":attach,"orderid":orderid}
        }
    })

}



/**
 * @name cash
 * 单笔转账
 * 请不要暴露此接口
 */
exports.cash = function(config){
    let api = 'alipay.fund.trans.toaccount.transfer';
    let opts = {
        "out_biz_no": config["orderid"],
        "payee_type": 'ALIPAY_LOGONID',
        "payee_account": config["account"],
        "amount" : config["rmb"],
    }
    if(config["payer"]){
        opts['payer_show_name'] = config["payer"];
    }
    if(config["payee"]){
        opts['payee_real_name'] = config["payee"];
    }
    if(config["describe"]){
        opts['remark'] = config["describe"];
    }

    let url = 'https://openapi.alipay.com/gateway.do';
    return alipay_sign.call(this,api,opts,null,1).then(body=>{
        return this.library("request/get",url,body,true)
    }).then(ret=>{
        if(!ret){
            return this.error('alipay return error',ret);
        }
        if( !ret['alipay_fund_trans_toaccount_transfer_response'] ||  ret['alipay_fund_trans_toaccount_transfer_response']['code']!='10000'){
            return this.error('alipay return error',JSON.stringify(ret));
        }
        return ret['alipay_fund_trans_toaccount_transfer_response'];
    })
}


function alipay_sign(api,content,notifyurl,json){
    let  data = {};
    data["app_id"] = this.opensdk.setting.appid;
    data["method"] = api;
    data["format"] = "JSON";
    data["charset"] = "utf-8";
    data["sign_type"] = sign_type;
    data["timestamp"] = this.library("time/format","yyyy-MM-dd hh:mm:ss");
    data["version"] = "1.0";
    data["biz_content"] = JSON.stringify(content);
    if(notifyurl){
        data["notify_url"] = notifyurl;
    }
    ///////////////////////////////////开始签名//////////////////////////////////////
    let retArr = [],signArr=[];
    let keys = Object.keys(data).sort();
    for(let k of keys){
        let v = data[k];
        if(!v){
            continue;
        }
        if(typeof v === "object"){
            v = JSON.stringify(v);
        }
        retArr.push(k+"="+encodeURIComponent(v));
        signArr.push(k+"="+v);
    }
    let signStr = signArr.join("&");
    return RSA2.sign.call(this,signStr).then(singRet=>{
        data['sign'] =singRet;
        retArr.push("sign="+encodeURIComponent(singRet));
        return json ? data : retArr.join("&") ;
    })

}



var RSA2 = {};
RSA2.sign = function RSA2_sign(str) {
    return Promise.resolve().then(()=>{
        if(!this.opensdk.setting.PrivateKey){
            return Promise.reject("opensdk.setting.PrivateKey empty")
        }
        return this.library("promise",fs.readFile,this.opensdk.setting.PrivateKey)
    }).then((PrivateKey)=>{
        let signer = crypto.createSign('RSA-SHA256');
        return signer.update(str).sign(PrivateKey, "base64");
    })
};

RSA2.verify = function verifySign(params, sign) {
    return Promise.resolve().then(()=>{
        if(!this.opensdk.setting.PublicKey){
            return Promise.reject("opensdk.setting.PublicKey empty")
        }
        return this.library("promise",fs.readFile,this.opensdk.setting.PublicKey)
    }).then((PublicKey)=>{
        let verify = crypto.createVerify('RSA-SHA256');
        let str = RSA2.params(params);
        return verify.update(str).verify(PublicKey, sign,"base64");
    })
}

RSA2.params = function RSA2_params(params) {
    if(typeof params !== "object"){
        return params;
    }
    let keys = Object.keys(params).sort();
    let sPara = [];
    for(let k of keys){
        if(params[k]){
            sPara.push( k+"="+params[k]);
        }
    }
    return sPara.join("&");
}